package sslsockets;

import java.io.IOException;
import java.net.ConnectException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

public abstract class SSLSocketHandler {

	/**
	 * 
	 * @param port int port on which we'll be listening
	 * @param trustKeyStore KeyStore object with entries (certificates, keys, etc) that we trust
	 * 						In case of server authentication only this should be empty.
	 * @param keyStore KeyStore object with our keys, certificates etc.
	 * @param password char[] password to the keyStore
	 * @return SSLServerSocket s all ready to "Socket socket = s.accept()"
	 * @throws KeyStoreException
	 * @throws UnrecoverableKeyException
	 * @throws IOException
	 */
	public static SSLServerSocket createServerSocket(int port, KeyStore trustKeyStore, KeyStore keyStore, char[] password)
			throws KeyStoreException, UnrecoverableKeyException, IOException{
		SSLServerSocket sslSocket = null;
		TrustManagerFactory tmf = null;
		KeyManagerFactory kmf = null;

		// create all the stuff needed to init SSLContext
		// (needed for SSLSocketFactory (needed for SSLSocket))
		try{
			tmf = TrustManagerFactory.getInstance("SunX509");
			kmf = KeyManagerFactory.getInstance("SunX509");
			tmf.init(trustKeyStore);
			kmf.init(keyStore, password);
			
			// create, init SSLContext
    		SSLContext sslCtx = SSLContext.getInstance("TLS");
    		sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    		
    		// create SSLSocketFactory and SSLSocket
    		SSLServerSocketFactory sslSocketFactory = (SSLServerSocketFactory)sslCtx.getServerSocketFactory();
    		//SSLServerSocketFactory sslSocketFactory = (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
    		sslSocket = (SSLServerSocket)sslSocketFactory.createServerSocket(port);
    		
//    		for (String s:sslSocket.getSupportedCipherSuites()){
//    			System.out.println(s);
//    		}
//    		//String[] cipherSuites = {"SSL_RSA_WITH_RC4_128_SHA"};
//    		String[] cipherSuites = sslSocket.getSupportedCipherSuites();
//    		sslSocket.setEnabledCipherSuites(cipherSuites);

		}
		catch (NoSuchAlgorithmException e){
			e.printStackTrace();
			System.exit(1);
		} catch (KeyManagementException e) {
			e.printStackTrace();
			System.exit(1);
		}
		
		return sslSocket;
	}
	
	/**
	 * 
	 * @param host String name of the host we're connecting to
	 * @param port int port to which we want to connect to
	 * @param trustKeyStore KeyStore object with entries (certificates, keys, etc) that we trust.
	 * @param keyStore KeyStore object with our keys, certificates etc.
	 * @param password char[] password to the keyStore
	 * @return SSLSocket s
	 * @throws KeyStoreException
	 * @throws UnrecoverableKeyException
	 * @throws IOException
	 */	
	public static SSLSocket createSocket(String host, int port, KeyStore trustKeyStore, KeyStore keyStore, char[] password)
			throws KeyStoreException, UnrecoverableKeyException, IOException, ConnectException{
		SSLSocket sslSocket = null;
		TrustManagerFactory tmf = null;
		KeyManagerFactory kmf = null;

		// create all the stuff needed to init SSLContext
		// (needed for SSLSocketFactory (needed for SSLSocket))
		try{
			tmf = TrustManagerFactory.getInstance("SunX509");
			kmf = KeyManagerFactory.getInstance("SunX509");
			tmf.init(trustKeyStore);
			kmf.init(keyStore, password);

			// create, init SSLContext
    		SSLContext sslCtx = SSLContext.getInstance("TLS");
    		sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    		
    		// create SSLSocketFactory and SSLSocket
    		SSLSocketFactory sslSocketFactory = (SSLSocketFactory)sslCtx.getSocketFactory();
    		sslSocket = (SSLSocket)sslSocketFactory.createSocket(host,port);
    		
//    		for (String s:sslSocket.getSupportedCipherSuites()){
//    			System.out.println(s);
//    		}
//    		//String[] cipherSuites = {"SSL_RSA_WITH_RC4_128_SHA"};
//    		String[] cipherSuites = sslSocket.getSupportedCipherSuites();
//    		sslSocket.setEnabledCipherSuites(cipherSuites);

		}
		catch (NoSuchAlgorithmException e){
			e.printStackTrace();
			System.exit(1);
		} catch (KeyManagementException e) {
			e.printStackTrace();
			System.exit(1);
		}
		
		return sslSocket;
	}
}
